#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 时间     : 2019-12-13 09:03:35
# 作者     : DL (584054432@qq.com)
# 网址     : https://gitee.com/dingliangPython/
# 软件版本 : Python3.7.3
# 功能     ：

import os
import pickle
import re
import sqlite3

from configobj import ConfigObj

from tools import set_message


class Config(object):
    """docstring for Config"""

    def __init__(self):
        super(Config, self).__init__()
        self.path = './config.dat'
        self.read = self.get_config
        self.write = self.set_config

    def set_config(self, data):
        with open(self.path, 'wb') as f:
            pickle.dump(data, f)
        return data

    def get_config(self, table_name = None, key = None):
        if not os.path.exists(self.path):
            config = {
                    'log': {
                            'LogLevel': 10,  # 等级
                            'LogSave': '1',  # 是否存储日志
                            'LogSavePath': './log',  # 存储日志路径
                            'LogSaveCycle': 1,  # 周期
                            'LogSaveUnit': 'H',  # 周期单位 D,H,M,S,天，时，分，秒
                            'LogSaveNumber': 168,  # 存储日志个数
                            'LogSaveSize': 5,  # 文件大小
                            },
                    'app': {'name': None, 'password': False},
                    'sdk': {'start': False},
                    'server': {}
                    }
            with open(self.path, 'wb') as f:
                pickle.dump(config, f)
            return config
        # 读取配置
        with open(self.path, 'rb') as f:
            data = pickle.load(f)
        # 返回表数据
        if table_name:
            if not isinstance(data.get(table_name), dict):
                data.update({table_name: {}})
                self.write(data)
            return data.get(table_name)
        # 返回key数据
        if table_name and key:
            return self.read(table_name).get(key)

        return data


class loadIni(object):
    """docstring for loadIni"""

    def __init__(self, file = None, encoding = 'utf8'):
        super(loadIni, self).__init__()
        self.file = file
        self.encoding = encoding
        self.ini = self.__load()

    def __load(self):
        _file = None if not self.file else self.file
        for f in (self.file, './config.ini', './config/config.ini'):
            if f and os.path.exists(f):
                _file = f
                break
        if not _file:
            set_message("配置：config.ini，不存在，请检测配置文件")
            return
        obj = ConfigObj(os.path.abspath(_file), write_empty_values = True, stringify = True, encoding = self.encoding)

        # 转换数值
        for k, v in obj.items():
            if v:
                for key, value in v.items():
                    if value.lower() == 'false':
                        obj[k][key] = False
                        continue
                    elif value.lower() == 'true':
                        obj[k][key] = True
                        continue
                    elif value.isnumeric():
                        obj[k][key] = int(value)
                        continue
                    elif re.findall('^\d+\.\d+$', value):
                        obj[k][key] = float(value)
                        continue
        return obj

    def read(self):
        return self.ini

    def write(self, as_save = None):
        # return self.ini.write()
        if not as_save:
            return self.ini.write()
        else:
            return self.ini.write(as_save)

    def __call__(self):
        return self.read()


LoadINI = loadIni


class loadSqlite(object):
    """docstring for loadSqlite"""

    def __init__(self, db = './config.db'):
        super(loadSqlite, self).__init__()
        self.configDb = db

    def conn(self):
        file = os.path.abspath(self.configDb)
        if os.path.exists(file):
            conn = sqlite3.connect(self.configDb)
            return conn
        else:
            set_message("程序缺少配置文件：：{}".format(file))
            os._exit(0)
            return

    def read(self):
        conn = self.conn()
        cursor = conn.cursor()
        configDict = {}
        sql = "SELECT NAME FROM SQLITE_MASTER WHERE TYPE = 'table' AND NAME != 'sqlite_sequence' ORDER BY NAME;"
        table = [t.get('name') for t in self.loadSql(sql)]
        if table:
            for t in table:
                sql = "SELECT * FROM {} ;".format(t)
                data = self.loadSql(sql)
                if not data: continue
                if t != 'databaseConnect':
                    data = data[0]
                configDict.setdefault(t, data)
            cursor.close()
            conn.close()
            return configDict

    # 查询数据
    def loadSql(self, sql):
        conn = self.conn()
        cursor = conn.cursor()
        cursor.execute(sql)
        value = cursor.fetchall()
        data = []
        if value and len(value) >= 1:
            field = tuple([d[0] for d in cursor.description])
            for v in value:
                data.append(dict(zip(field, v)))
            cursor.close()
            conn.close()
            return data
        else:
            return None

    def write(self, newConfig):
        conn = self.conn()
        cursor = conn.cursor()
        oldConfig = self.read()
        for k, v in newConfig.items():
            if k != 'databaseConnect':
                s = ','.join(["{}='{}'".format(key, value) for key, value in v.items()])
                sql = "UPDATE {} SET {} ;".format(k, s)
                res = cursor.execute(sql)
                conn.commit()
                if not res:
                    sql = "INSERT INTO {} ({}) VALUES({})".format(k, ''.join(tuple(v.keys()), ''.join(
                            ["'{}'".format(val)] for val in tuple(v.values()))))
                    cursor.execute(sql)
            if k == 'databaseConnect':
                for row in v:
                    name = row['name']
                    if not oldConfig.get('databaseConnect'): oldConfig.update({'databaseConnect': []})
                    if name in [vv.get('name') for vv in oldConfig['databaseConnect']]:
                        s = ','.join(["{}={}".format(key, "'%s'" % value if value else 'NULL') for key, value in
                                      row.items()])
                        sql = "UPDATE {} SET {} WHERE NAME='{}';".format(k, s, name)
                        cursor.execute(sql)
                        conn.commit()
                    else:
                        keys = (str(v) for v in row.keys())
                        values = ("'{}'".format(v) if v else 'NULL' for v in row.values())
                        sql = "INSERT INTO databaseConnect ({}) VALUES ({});".format(','.join(keys), ','.join(values))
                        cursor.execute(sql)
                        conn.commit()
                newNames = [row.get('name') for row in v]
                if not oldConfig.get('databaseConnect'): return
                for row in oldConfig['databaseConnect']:
                    oldName = row.get('name')
                    if oldName not in newNames:
                        sql = "DELETE FROM databaseConnect WHERE name='{}'".format(oldName)
                        cursor.execute(sql)
                        conn.commit()
        cursor.close()
        conn.close()

    def execSql(self, sql):
        conn = self.conn()
        cursor = conn.cursor()
        cursor.execute(sql)
        rec = cursor.rowcount
        conn.commit()
        cursor.close()
        conn.close()
        return rec


if __name__ == '__main__':
    db = r'D:\CODE\PYTHON\Common\config.db'
    app = loadSqlite(db)
    config = app.read()
    print(config)

    config['databaseConnect'][0]['name'] = 'xx'
    config['appConfig']['AppId'] = '123'
    # print('new',config)
    app.write(config)